#pragma once
#include <Windows.h>
#include <xnamath.h>
#include <vector>
#include <D3D11.h>
#include <d3dx11effect.h>
#include <vector>

class IslandApp;
class Mesh;
class FireObject;

const int MAX_EMITTERS = 144;
const int MAX_PARTICLES = 100000;


struct Intersection
{
	XMFLOAT4 position;
	XMFLOAT4 normal;
	float t;
	unsigned int ray_id;
	unsigned int ID;
};

struct Emitter 
{
	XMFLOAT4 position;
	XMFLOAT4 direction;
	unsigned int ID;
	bool	active;
	XMFLOAT2 params;
};

struct FireParticle
{
	XMFLOAT4 position;
	XMFLOAT4 direction;
	XMFLOAT4 params;		// emitter : .X: ID, .Y: active: Z: age .W: type
							// particle: .X: age .Y: alpha   Z:     .W: type
};


struct Ray
{
	XMFLOAT4 o;
	XMFLOAT4 d;
};


enum { mADD, mDELETE, mADD_DIRECTION };

class FireSystem
{
	public:
		FireSystem();			

		~FireSystem();

		void setAppHandle(IslandApp* h) { mApp = h; }
		
		void setEditMode(bool v);
		void addObject(FireObject* m);
		
		void init(ID3D11Device* g_dev, ID3D11DeviceContext* g_ctx, ID3D11InputLayout* layout);
		
		
		
		bool onFire() const { return bOnFire; }
		void onFire(bool v);
		void run(float dt);

		void generateProcEmitters();


		float val;


		float	m_minTriangleArea;
		float	m_maxTriangleArea;
		UINT	m_minTriSamples;
		UINT	m_maxTriSamples;

		void stopFire();

		void setWindVector(float dir[]);
		void setWindPower(float v) { m_windPower = v; }

	private:

		float m_windPower;

		std::vector<int>	output;

		XMFLOAT3	m_windDirection;

		ID3D11Device*	g_dev;
		ID3D11DeviceContext*	g_ctx;
		ID3D11InputLayout*	g_layout;
		
		float m_particleAge;

		bool bFadeOut;
		bool bOnFire;
		bool bHasNewRay;
		bool bDelete;
		bool bActive;
		UINT mNumEmitters;

		void initBuffers();
		void buildEmittersBuffer();
		
		void passUpdateParticles(float dt);
		void passUpdateHeat();
		void passDrawParticles();
		

		unsigned int getNearestEmitter(XMFLOAT4 pos);

		IslandApp*	mApp;
		ID3DX11Effect*	mFx;
		std::vector<FireObject*>	objects;
		std::vector<Intersection> collision_results;
		std::vector<Ray> rays;
		FireParticle emitters[MAX_EMITTERS];
		unsigned int emitter_index;

		unsigned int mState;

		void createEffect(const char* filename, ID3DX11Effect** _fx);
		bool loadEffect(const char* filename, std::vector<char> &compiledShader) const;
		void createLayouts();

		ID3D11ShaderResourceView*	m_srvFireParticle;

		ID3DX11Effect* mFxEmitParticles;
		ID3DX11Effect* mFxUpdateParticles;
		ID3DX11Effect* mFxDrawParticles;
		ID3DX11Effect* mFxUpdateHeat;
		ID3DX11Effect* mFxProceduralEmitters;

		
		ID3D11Buffer*	vb_emitters;
		ID3D11Buffer*	vb_particles0;
		ID3D11Buffer*	vb_particles1;

		ID3D11InputLayout*	mLayout_Emitter;
		ID3D11InputLayout*  mLayout_FireParticle;

		ID3D11Texture2D* tex_heat;
		ID3D11Texture2D* tex_emitters;
		ID3D11ShaderResourceView* srv_heat;
		ID3D11ShaderResourceView* srv_noise;

		ID3D11ShaderResourceView* srv_emitters;
		ID3D11RenderTargetView*   rtv_emitters;

		XMFLOAT3 ray_o;
		XMFLOAT3 ray_d;

		bool bFirstRun;
		float mHeatThreshold;
		bool mEditMode;
		int mScreenX;
		int mScreenY;
};